# -*-coding:utf8-*-
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
import re
from selenium import webdriver
import time
from HnuclassSystem import sql


class AccountError(Exception):
    def __init__(self, *args: object) -> None:
        #super().__init__(*args)
        print('账号或密码错误')

class Hnuclass:
    def __init__(self, account, password, qq) -> None:
        self.account = account
        self.password = password
        self.qq = qq
        self.all_class = self.getClass(self.getHtml())
        pass


    def getHtml(self) -> str:
        '''
        使用账号密码获取课表网页源代码
        '''

        # 浏览器的各项设置，不建议更改
        options = webdriver.ChromeOptions()
        options.add_argument('--no-sandbox') # 解决DevToolsActivePort文件不存在的报错
        options.add_argument('--start-maximized')#浏览器最大化
        options.add_argument('--disable-gpu') # 谷歌文档提到需要加上这个属性来规避bug
        options.add_argument('--hide-scrollbars') # 隐藏滚动条, 应对一些特殊页面
        options.add_argument('blink-settings=imagesEnabled=false') # 不加载图片, 提升速度
        options.add_argument('--headless') # 浏览器不提供可视化页面. linux下如果系统不支持可视化不加这条会启动失败
        options.add_argument('--disable-infobars') # 禁用浏览器正在被自动化程序控制的提示
        driver = webdriver.Chrome(options=options)
        #driver.maximize_window()

        try:
            driver.get('https://jxgl.hainanu.edu.cn/jsxsd/xskb/xskb_list.do')
            driver.find_element_by_name('username').send_keys(self.account) #发送帐号名
            driver.find_element_by_id('password').send_keys(self.password,Keys.ENTER) #发送密码并回车
            time.sleep(2)
        except:
            print('登录时失败')

        # 正确的账号密码会在登陆之后跳转到教务，页面标题为学生个人中心，不正确的标题还是统一身份认证
        if driver.title != '学生个人中心':
            raise AccountError
        try:
            # 点击培养管理
            driver.find_elements_by_xpath('//*[@id="calender_user_schedule"]')[2].click()
            time.sleep(2)
            # 点击理论课表
            driver.find_element_by_xpath('//*[@id="LeftMenu1_divChildMenu"]/ul[2]/li[1]/a').click()
            time.sleep(2)
        except:
            print('未找到网页上对应按钮。可能是网页更改了布置')
        pageCode = driver.page_source
        #关闭浏览器
        driver.quit()

        return pageCode

    
    def getClass(self, html) -> list:
        '''
        从网页源代码中获取课程信息
        '''
        soup = BeautifulSoup(html, 'html.parser') # 转成bs对象，使用bs的find寻找课表
        classTable = soup.find(id='kbtable').find('tbody').find_all('tr')
        allClass = []

        # section 节次
        # 先对二维数组查找节次
        for section in range(1, 6):
            section_class = classTable[section].find_all('td')
            
            # 再查找周几
            for day in range(1, 8):
                classes = section_class[day - 1]
                try:
                    classContent = classes.find('div', class_ = 'kbcontent')
                    if classContent.string:continue
                    classContentStr = str(classContent) # 用来检测有几个老师上课
                    times = classContentStr.count('---------------------') + 1 #判断课程是否为多老师/多课程的情况

                    if times == 1:
                        # 生成课表对象
                        hnuclass = {}
                        '''
                        正则表达式提取一下
                        .+?(考)
                        '''
                        pattern = re.compile(r'.+?(考.\))')

                        hnuclass['name'] = pattern.search(classContent.text).group()
                        hnuclass['teacher'] = classContent.find(title = '老师').string
                        hnuclass['week'] = getSection(classContent.find(title = '周次(节次)').string[:-11]) # 改一下，把节次去掉，只留周次
                        hnuclass['room'] = classContent.find_all(title = '教室')[1].string
                        hnuclass['position'] = (day, section)
                        hnuclass['stuid'] = self.account
                        hnuclass['qq'] = self.qq
                        allClass.append(hnuclass)
                    else:
                        # 可能出现多老师/多课程的情况
                        for _ in range(times):
                            hnuclass = {}
                            hnuclass['position'] = (day, section)
                            hnuclass['teacher'] = classContent.find(title = '老师').string
                            hnuclass['week'] = getSection(classContent.find(title = '周次(节次)').string[:-11])
                            hnuclass['stuid'] = self.account
                            hnuclass['qq'] = self.qq
                            if _ == 0:
                                pattern = re.compile(r'.+?(考.\))')
                                hnuclass['name'] = pattern.search(classContent.text).group()
                                hnuclass['room'] = classContent.find_all(title = '教室')[1].string
                            else:
                                pattern = re.compile(r'\-\-.+?(考.\))')
                                hnuclass['name'] = pattern.search(classContent.text).group()[21:]
                                hnuclass['room'] = classContent.find_all(title = '教室')[2].string
                        
                        
                            allClass.append(hnuclass)
                            classContent = classContent.find_all('font')[2] # 指向下一门课/下一个老师
                        

                except :
                    continue
    
        return allClass 


    def insertAllClass(self):
        '''
        向数据库中插入所有课程
        '''
        #database = sql.Database(config.DATABASE_ADDRESS, config.DATABASE_ACCOUNT, config.DATABASE_PASSWORD, config.DATABASE_NAME, config.DATABASE_PORT)
        for class_ in self.all_class:
            try:
                status = sql.database.insertClass(class_)
                if not status:
                    print(f'{class_["name"]}课程添加失败')
                    return False
            except:
                print(f'{class_["name"]}课程添加失败')
                return False
        return True




# 整理节次
def getSection(section : str) -> str:
    '''
    将x-x的形式变成"A,B,C"的形式，返回字符串
    '''
    res = ''
    # 先解析x-x的
    pattern = re.compile(r'\d+-\d+')
    # search返回第一个匹配, findall返回所有匹配(返回列表)
    tempres = pattern.findall(section)
    for r in tempres:
        # 删除原来的
        section = section.replace(r, '')# 将原来字符串里面的替换成空
        p = re.compile(r'\d+')
        for i in range(int(p.findall(r)[0]), int(p.findall(r)[1]) + 1):
            res = res + ',' + str(i)
    
    # 再解析单个的
    p = re.compile(r'\d+')
    tempres = p.findall(section)
    for r in tempres:
        res = res + ',' + r
    
    # 最后开头有个逗号，去掉
    return res[1:]